#pragma once

#include "LeDocumentObject_global.h"

#include "IDocumentObject.h"

#include <QObject>
#include <QList>
#include <QMap>

namespace LDO
{

    class IDocumentObjectFactory;

    // use QObject findChildren, qobject_cast (instead of type(), ...

    class DocumentPrivate;
    class LDO_EXPORT Document: public IDocumentObject
    {
        Q_OBJECT
        Q_DISABLE_COPY(Document)
        Q_DECLARE_PRIVATE(Document)
        QScopedPointer<DocumentPrivate> const d_ptr;

        Q_PROPERTY(QString fileName READ fileName WRITE setFileName NOTIFY fileNameChanged)

    public:
        enum
        {
            Type = 1
        };
        explicit Document(QObject *parent = nullptr);
        ~Document();

        bool registerFactory(IDocumentObjectFactory *factory);

        QString fileName() const;

        IDocumentObject *createObject(const QString &typeName);
        IDocumentObject *createObject(int typeId);
        template<class T> T *createObject();
        IDocumentObject *addObject(const QString &typeName);
        IDocumentObject *addObject(int typeId);
        template<class T> T *addObject();
        template<class T> QList<T> objects() const;

        QString iconName(const IDocumentObject *object) const;

        void setSelectedObjects(const QList<IDocumentObject *> &selectedObjects);
        const QList<IDocumentObject *> selectedObjects() const;
        void clearSelectedObjects();

    signals:
        void fileNameChanged(QString fileName);
        void selectedObjectsChanged(const QList<IDocumentObject*> &current, const QList<IDocumentObject*> &previous);

    public slots:
        void setFileName(QString fileName);

        // IDocumentObject interface
    public:
        virtual int objectType() const override { return Type; }
    };

    template<class T>
    T *Document::createObject()
    {
        return qobject_cast<T*>(createObject(T::Type));
    }


    template<class T>
    T *Document::addObject()
    {
        return qobject_cast<T*>(addObject(T::Type));
    }

    template<class T>
    QList<T> Document::objects() const
    {
        QList<T> result;
        for (auto object: children())
        {
            T tObject = qobject_cast<T>(object) ;
            if (tObject != nullptr)
                result.append(tObject);
        }
        return result;
    }

}

Q_DECLARE_METATYPE(LDO::Document*)
